
import UIKit
import CommonCrypto


public enum ToolBoxSupercar {
    /// zero
    case zero
    /// one
    case injured
    /// three
    case tactory
    /// four
    case energetic
}


extension String {
    func md5() -> String {
        let messageData = self.data(using: .utf8)!
        var digestData = Data(count: Int(CC_MD5_DIGEST_LENGTH))
        
        _ = digestData.withUnsafeMutableBytes { digestBytes -> UInt8 in
            messageData.withUnsafeBytes { messageBytes -> UInt8 in
                let messageLength = CC_LONG(messageData.count)
                CC_MD5(messageBytes.baseAddress, messageLength, digestBytes.baseAddress)
                return 0
            }
        }
        
        return digestData.map { String(format: "%02hhx", $0) }.joined()
    }
}


@MainActor
class FFExcitement: NSObject {
    
    private var drive = ""
    private var fast = ""
    private var drift = FFDriftKeys.donut
    
    func screwdriverHammer(_ reality: [String: Any],
                           certain: [String: String],
                           tires: String,
                           drive: String,
                           fast: String,
                           tcriminal: String,
                           ustreet: String,
                           supercar: ToolBoxSupercar) -> [String: Any] {
        
        self.drive = drive
        self.fast = fast
        
        let time = peopleRadar()
        let recent = changingHiring()
        let side = FFAdrenaline.transmission()
        let hig = FFAdrenaline.enginePower()
        
        var tmp: [String: Any] = [
            drift.ff_data: reality,
            drift.ff_clientLanguage :tires,
            drift.ff_os:"2",
            drift.ff_channel:"app_store",
            drift.ff_clientVersion:side,
            drift.ff_deviceId:hig,
            drift.ff_version:"2.0",
            drift.ff_clientTime:time,
            drift.ff_nonce:recent,
            "appId":self.drive
        ]
        
        tmp[drift.ff_token] = tcriminal
        tmp[drift.ff_userId] = ustreet
        
        if supercar == .injured {
            tmp[drift.ff_sign] = spareTireInjured(certain, hig: hig, ret: recent, time: time)
        }else if supercar == .tactory {
            tmp[drift.ff_sign] = spareTireTactory(certain, hig: hig, ret: recent)
        }else if supercar == .energetic {
            tmp[drift.ff_sign] = spareTireEnergetic(certain, hig: hig, ret: recent)
        }else {
            tmp[drift.ff_sign] = spareTireZero()
        }
        
        return tmp
    }
    /// three
    func spareTireTactory(_ certain: [String: String], hig: String, ret: String) -> String {
        
        var tmp = certain
        
        tmp["appId"] = self.drive
        tmp["deviceId"] = hig
        tmp["version"] = "2.0"
        tmp["channel"] = "app_store"
        tmp["nonce"] = ret
        
        let street = tmp.values.sorted(by: { $0 > $1 })
        
        let highway = street.joined(separator: ";")
        
        return (highway + self.fast).md5().uppercased()
    }
    
    /// one
    func spareTireInjured(_ certain: [String: String], hig: String, ret: String, time: String) -> String {
        
        var tmp = certain
        
        tmp["appId"] = self.drive
        tmp["deviceId"] = hig
        tmp["channel"] = "app_store"
        tmp["nonce"] = ret
        tmp["version"] = "2.0"
        tmp["clientTime"] = time
        tmp["os"] = "2"
        
        let street = tmp.values.sorted().joined(separator: "&")
        
        let highway = street.md5().uppercased()
        
        return (highway + self.fast).md5().uppercased()
    }
    
    /// four
    func spareTireEnergetic(_ certain: [String: String], hig: String, ret: String) -> String {
        var tmp = certain
        
        tmp["appId"] = self.drive
        tmp["deviceId"] = hig
        tmp["channel"] = "app_store"
        tmp["nonce"] = ret
        tmp["version"] = "2.0"
        
        let street = tmp.values.sorted(by: { $0 > $1 })
        
        let highway = street.joined(separator: "*") + "MD" + self.fast
        
        return highway.md5().uppercased()
    }
    
    /// zero
    func spareTireZero() -> String {
        
        let charset = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
        let charsetArray = Array(charset)
        var result = ""
        
        for _ in 0..<32 {
            let randomIndex = Int(arc4random_uniform(UInt32(charsetArray.count)))
            result.append(charsetArray[randomIndex])
        }
        
        return result.uppercased()
    }
    
    
    private func peopleRadar() -> String {
        return String(Int64(Date().timeIntervalSince1970 * 1000))
    }
    
    private func changingHiring() -> String {
        let characters = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
        var result = ""
        result.reserveCapacity(16)
        
        for _ in 0..<16 {
            let randomIndex = Int(arc4random_uniform(UInt32(characters.count)))
            let character = characters[characters.index(characters.startIndex, offsetBy: randomIndex)]
            result.append(character)
        }
        
        return result
    }
}
